﻿using Action = Styx.TreeSharp.Action;
using Styx;
using Styx.Common;
using Styx.CommonBot;
using Styx.CommonBot.Routines;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
using System.Diagnostics;


namespace RaidHunter
{

    public partial class Main : CombatRoutine
    {
        public override string Name { get { return "Endgame Survival Routine by Pasterke"; } }
        public override WoWClass Class { get { return WoWClass.Hunter; } }
        LocalPlayer Me { get { return StyxWoW.Me; } }

        public static Stopwatch RapidFireTimer = new Stopwatch();

        public override bool WantButton { get { return true; } }

        public override void OnButtonPress()
        {
            Form1 ConfigForm = new Form1();
            ConfigForm.ShowDialog();
        }

        public override void Initialize()
        {
            Updater.CheckForUpdate();
            Lua.Events.AttachEvent("MODIFIER_STATE_CHANGED", HandleModifierStateChanged);
        }
        public override void Pulse()
        {
            try
            {
                if (!Me.Combat
                    && RapidFireTimer.IsRunning)
                {
                    RapidFireTimer.Reset();
                }
            }
            catch {}
        }
        public override bool NeedRest { get { return true; } }

        public override void Rest() 
        {
            if (Me.GotAlivePet
                && SpellManager.HasSpell(MendPet)
                && Me.Pet.HealthPercent <= RaidHunterSettings.myPrefs.mendpetpercent
                && !buffExists(MendPet, Me.Pet))
            {
                if (SpellManager.CanCast(MendPet))
                {
                    SpellManager.Cast(MendPet);
                    LogMsg("Mend Pet out of Combat", 2);
                    lastCast = MendPet;
                }
            }
        
        }

        #region Pull

        public override void Pull() { }
         
        #endregion

        #region Pull Buffs

        public override bool NeedPullBuffs { get { return false; } }

        public override void PullBuff() { }

        #endregion

        #region Pre Combat Buffs

        public override bool NeedPreCombatBuffs
        {
            get
            {
                if (!buffExists(FeignDeath, Me))
                {
                    CallPet();
                    ReviveMyPet();

                    if (SpellManager.HasSpell(TrapLauncher)
                        && !buffExists(TrapLauncher, Me))
                    {
                        if (SpellManager.CanCast(TrapLauncher))
                        {
                            SpellManager.Cast(TrapLauncher, Me);
                            LogMsg("Trap Launcher", 2);
                            lastCast = TrapLauncher;
                        }
                    }
                    if (SpellManager.HasSpell(AspectIronHawk)
                        && !buffExists(AspectIronHawk, Me))
                    {
                        if (SpellManager.CanCast(AspectIronHawk))
                        {
                            SpellManager.Cast(AspectIronHawk);
                            LogMsg("Aspect of the Iron Hawk", 2);
                            lastCast = AspectIronHawk;
                        }
                    }
                }
                return false;
            }
        }
        public override void PreCombatBuff() { }
         
        #endregion 

        #region Heal

        public override bool NeedHeal { get { return false; } }

        public override void Heal() { }
        
        #endregion

        #region Falling

        public void HandleFalling() { }

        #endregion

        public override bool NeedCombatBuffs { get { return false; } }

        public override void CombatBuff() { }

        public override void Combat()
        {
            if (Paused)
            {
                return;
            }
            if (buffExists(FeignDeath, Me))
            {
                return;
            }
            if (SpellManager.HasSpell(TrapLauncher)
                    && !buffExists(TrapLauncher, Me))
            {
                if (SpellManager.CanCast(TrapLauncher))
                {
                    SpellManager.Cast(TrapLauncher, Me);
                    LogMsg("Trap Launcher", 2);
                    lastCast = TrapLauncher;
                }
            }
            if (SpellManager.HasSpell(AspectIronHawk)
                && !buffExists(AspectIronHawk, Me))
            {
                if (SpellManager.CanCast(AspectIronHawk))
                {
                    SpellManager.Cast(AspectIronHawk);
                    LogMsg("Aspect of the Iron Hawk", 2);
                    lastCast = AspectIronHawk;
                }
            }

            CallPet();
            ReviveMyPet();
            AlchemistFlask();
            HealthStone();

            if (Me.GotAlivePet
                && SpellManager.HasSpell(MendPet)
                && !buffExists(MendPet, Me.Pet)
                && Me.Pet.HealthPercent <= RaidHunterSettings.myPrefs.mendpetpercent)
            {
                if (SpellManager.CanCast(MendPet))
                {
                    SpellManager.Cast(MendPet);
                    LogMsg("Mend Pet in Combat", 2);
                    lastCast = MendPet;
                }
            }
            myFlask();
            myPotion();

            if (gotTarget
                && addCount >= RaidHunterSettings.myPrefs.startaoe
                && !PauseAoe)
            {
                AoeRotation();
            }
            if (gotTarget
                && addCount < RaidHunterSettings.myPrefs.startaoe)
            {
                MainRotation();
            }
        }

        void MainRotation()
        {
            NeedMisdirection();
            if (gotTarget
                && SpellManager.HasSpell(SilencingShot)
                && !spellOnCooldown(SilencingShot)
                && Me.CurrentTarget.IsCasting
                && Me.CanInterruptCurrentSpellCast
                && !Me.IsChanneling)
            {
                if (SpellManager.CanCast(SilencingShot))
                {
                    SpellManager.Cast(SilencingShot);
                    LogMsg("Silencing Shot", 3);
                    lastCast = SilencingShot;
                    return;
                }
            }
            if (gotTarget
                && SpellManager.HasSpell(SerpentSting)
                && !debuffExists(SerpentStingAura, Me.CurrentTarget)
                && lastCast != SerpentSting
                && !Me.IsChanneling)
            {
                if (SpellManager.CanCast(SerpentSting))
                {
                    SpellManager.Cast(SerpentSting);
                    LogMsg("Serpent Sting", 6);
                    lastCast = SerpentSting;
                    return;
                }
            }
            if (gotTarget
                && SpellManager.HasSpell(BlackArrow)
                && !debuffExists(BlackArrow, Me.CurrentTarget)
                && !spellOnCooldown(BlackArrow)
                && Me.FocusPercent >= 35
                && lastCast != BlackArrow
                && !Me.IsChanneling)
            {
                if (SpellManager.CanCast(BlackArrow))
                {
                    SpellManager.Cast(BlackArrow);
                    LogMsg("Black Arrow", 7);
                    lastCast = BlackArrow;
                    return;
                }
            }
            if (gotTarget
                && SpellManager.HasSpell(ExplosiveShot)
                && buffExists(LockAndLoad, Me)
                && !Me.IsChanneling)
            {
                if (SpellManager.CanCast(ExplosiveShot))
                {
                    SpellManager.Cast(ExplosiveShot);
                    LogMsg("Explosive Shot", 4);
                    lastCast = ExplosiveShot;
                    return;
                }
            }
            if (gotTarget
                && SpellManager.HasSpell(ExplosiveShot)
                && !spellOnCooldown(ExplosiveShot)
                && Me.FocusPercent >= 25
                && !Me.IsChanneling)
            {
                if (SpellManager.CanCast(ExplosiveShot))
                {
                    SpellManager.Cast(ExplosiveShot);
                    LogMsg("Explosive Shot", 4);
                    lastCast = ExplosiveShot;
                    return;
                }
            }
            if (gotTarget
                && SpellManager.HasSpell(Fervor)
                && !spellOnCooldown(Fervor)
                && UseTier60
                && !Me.IsChanneling
                && Me.FocusPercent <= 30)
            {
                if (SpellManager.CanCast(Fervor))
                {
                    SpellManager.Cast(Fervor);
                    LogMsg("Fervor", 0);
                    lastCast = Fervor;
                    return;
                }
            }
            if (gotTarget
                && SpellManager.HasSpell(DireBeast)
                && !spellOnCooldown(DireBeast)
                && UseTier60
                && !Me.IsChanneling)
            {
                if (SpellManager.CanCast(DireBeast))
                {
                    SpellManager.Cast(DireBeast);
                    LogMsg("Dire Beast", 0);
                    lastCast = DireBeast;
                    return;
                }
            }
            if (gotTarget
                && SpellManager.HasSpell(MurderOfCrows)
                && !spellOnCooldown(MurderOfCrows)
                && !debuffExists(MurderOfCrows, Me.CurrentTarget)
                && UseTier75
                && Me.FocusPercent >= 60
                && !Me.IsChanneling)
            {
                if (SpellManager.CanCast(MurderOfCrows))
                {
                    SpellManager.Cast(MurderOfCrows);
                    LogMsg("A Murder of Crows", 1);
                    lastCast = MurderOfCrows;
                    return;
                }
            }
            if (gotTarget
                && SpellManager.HasSpell("Lifeblood")
                && !spellOnCooldown("Lifeblood")
                && UseLifeblood)
            {
                if (SpellManager.CanCast("Lifeblood"))
                {
                    SpellManager.Cast("Lifeblood");
                    LogMsg("Lifeblood", 2);

                }
            }
            if (gotTarget
                && SpellManager.HasSpell(BlinkStrike)
                && !spellOnCooldown(BlinkStrike)
                && UseTier75
                && !Me.IsChanneling)
            {
                if (SpellManager.CanCast(BlinkStrike))
                {
                    SpellManager.Cast(BlinkStrike);
                    LogMsg("Blink Strike", 1);
                    lastCast = BlinkStrike;
                    return;
                }
            }
            if (gotTarget
                && SpellManager.HasSpell(LynxRush)
                && !spellOnCooldown(LynxRush)
                && UseTier75
                && !Me.IsChanneling)
            {
                if (SpellManager.CanCast(LynxRush))
                {
                    SpellManager.Cast(LynxRush);
                    LogMsg("Lynx Rush", 1);
                    lastCast = LynxRush;
                    return;
                }
            }
            if (gotTarget
                && SpellManager.HasSpell(Stampede)
                && !spellOnCooldown(Stampede)
                && lastCast != Stampede
                && Stamp
                && !Me.IsChanneling)
            {
                SpellManager.Cast(Stampede);
                LogMsg("Stampede", 2);
                lastCast = Stampede;
                return;
            }
            if (gotTarget
                && SpellManager.HasSpell(KillShot)
                && !spellOnCooldown(KillShot)
                && Me.CurrentTarget.HealthPercent <= 20
                && !Me.IsChanneling)
            {
                if (SpellManager.CanCast(KillShot))
                {
                    SpellManager.Cast(KillShot);
                    LogMsg("Kill Shot", 5);
                    lastCast = KillShot;
                    return;
                }
            }
            if (gotTarget
                && SpellManager.HasSpell(BloodFury)
                && !spellOnCooldown(BloodFury)
                && Bloodfury
                && !Me.IsChanneling)
            {
                if (SpellManager.CanCast(BloodFury))
                {
                    SpellManager.Cast(BloodFury);
                    LogMsg("Blood Fury", 2);
                    lastCast = BloodFury;
                    return;
                }
            }
            if (gotTarget
                && SpellManager.HasSpell(Berserking)
                && !spellOnCooldown(Berserking)
                && !Me.HasAura("Bloodlust")
                && !Me.HasAura("Heroism")
                && !Me.HasAura("Time Warp")
                && !buffExists(RapidFire, Me)
                && berserKing
                && !Me.IsChanneling)
            {
                if (SpellManager.CanCast(Berserking))
                {
                    SpellManager.Cast(Berserking);
                    LogMsg("Berserking", 2);
                    lastCast = Berserking;
                    return;
                }
            }
            if (gotTarget
                && SpellManager.HasSpell(RapidFire)
                && !spellOnCooldown(RapidFire)
                && !buffExists(RapidFire, Me)
                && Rapidfire
                && lastCast != RapidFire
                && !Me.IsChanneling)
            {
                if (SpellManager.CanCast(RapidFire))
                {
                    SpellManager.Cast(RapidFire);
                    RapidFireTimer.Restart();
                    LogMsg("Rapid Fire", 8);
                    lastCast = RapidFire;
                    return;
                }
            }
            if (gotTarget
                && SpellManager.HasSpell(Readiness)
                && !spellOnCooldown(Readiness)
                && !buffExists(RapidFire, Me)
                && UseReadiness
                && RapidFireTimer.IsRunning
                && lastCast != Readiness
                && !Me.IsChanneling)
            {
                if (SpellManager.CanCast(Readiness))
                {
                    SpellManager.Cast(Readiness);
                    LogMsg("Readiness", 9);
                    lastCast = Readiness;
                    return;
                }
            }

            UseTrinket1();
            UseTrinket2();
            UseEngiGloves();

            if (gotTarget
                && SpellManager.HasSpell(GlaiveToss)
                && !spellOnCooldown(GlaiveToss)
                && Me.FocusPercent >= 15
                && !Me.IsChanneling)
            {
                if (SpellManager.CanCast(GlaiveToss))
                {
                    if (!Me.GroupInfo.IsInRaid
                        && !Me.IsInInstance
                        && !buffExists(Misdirection, Me)
                        && !spellOnCooldown(Misdirection)
                        && lastCast != Misdirection)
                    {
                        Lua.DoString("RunMacroText('/cast [@focus,help][help][@pet,exists] Misdirection');");
                        {
                            LogMsg(">> Misdirection <<", 0);
                        }
                    }
                    SpellManager.Cast(GlaiveToss);
                    LogMsg("Glaive Toss", 1);
                    lastCast = GlaiveToss;
                    return;
                }
            }
            if (gotTarget
                && SpellManager.HasSpell(Powershot)
                && !spellOnCooldown(Powershot)
                && Me.FocusPercent >= 15
                && UseTier90
                && !Me.IsChanneling)
            {
                if (SpellManager.CanCast(Powershot))
                {
                    SpellManager.Cast(Powershot);
                    LogMsg("Powershot", 1);
                    lastCast = Powershot;
                    return;
                }
            }
            if (gotTarget
                && SpellManager.HasSpell(Barrage)
                && !spellOnCooldown(Barrage)
                && Me.FocusPercent >= 30
                && UseTier90
                && !Me.IsChanneling)
            {
                if (SpellManager.CanCast(Barrage))
                {
                    SpellManager.Cast(Barrage);
                    LogMsg("Barrage", 1);
                    lastCast = Barrage;
                    return;
                }
            }
            if (gotTarget
                && SpellManager.HasSpell(ArcaneShot)
                && Me.FocusPercent > 61
                && !Me.IsChanneling)
            {
                if (SpellManager.CanCast(ArcaneShot))
                {
                    SpellManager.Cast(ArcaneShot);
                    LogMsg("Arcane Shot focus dump", 10);
                    lastCast = ArcaneShot;
                    return;
                }
            }
            if (gotTarget
                && SpellManager.HasSpell(CobraShot)
                && (Me.FocusPercent <= 45
                || debuffTimeLeft(SerpentStingAura, Me.CurrentTarget) < 6000)
                && !Me.IsChanneling)
            {
                if (SpellManager.CanCast(CobraShot))
                {
                    SpellManager.Cast(CobraShot);
                    LogMsg("Cobra Shot" , 3);
                    lastCast = CobraShot;
                    return;
                }
            }
            return;
        }

        void AoeRotation()
        {
            if (gotTarget
                && SpellManager.HasSpell(ExplosiveShot)
                && buffExists(LockAndLoad, Me)
                && !Me.IsChanneling)
            {
                if (SpellManager.CanCast(ExplosiveShot))
                {
                    SpellManager.Cast(ExplosiveShot);
                    LogMsg("Explosive Shot", 6);
                    lastCast = ExplosiveShot;
                    return;
                }
            }
            if (gotTarget
                && SpellManager.HasSpell(ExplosiveShot)
                && !spellOnCooldown(ExplosiveShot)
                && Me.FocusPercent >= 25
                && !Me.IsChanneling)
            {
                if (SpellManager.CanCast(ExplosiveShot))
                {
                    SpellManager.Cast(ExplosiveShot);
                    LogMsg("Explosive Shot", 6);
                    lastCast = ExplosiveShot;
                    return;
                }
            }
            if (gotTarget
                && SpellManager.HasSpell(KillShot)
                && !spellOnCooldown(KillShot)
                && Me.CurrentTarget.HealthPercent <= 20
                && !Me.IsChanneling)
            {
                if (SpellManager.CanCast(KillShot))
                {
                    SpellManager.Cast(KillShot);
                    LogMsg("Kill Shot", 6);
                    lastCast = KillShot;
                    return;
                }
            }
            if (gotTarget
                && SpellManager.HasSpell(Fervor)
                && !spellOnCooldown(Fervor)
                && UseTier60
                && !Me.IsChanneling
                && Me.FocusPercent <= 30)
            {
                if (SpellManager.CanCast(Fervor))
                {
                    SpellManager.Cast(Fervor);
                    LogMsg("Fervor", 6);
                    lastCast = Fervor;
                    return;
                }
            }
            if (gotTarget
                && SpellManager.HasSpell(Barrage)
                && !spellOnCooldown(Barrage)
                && Me.FocusPercent >= 30
                && UseTier90
                && !Me.IsChanneling)
            {
                if (SpellManager.CanCast(Barrage))
                {
                    SpellManager.Cast(Barrage);
                    LogMsg("Barrage", 6);
                    lastCast = Barrage;
                    return;
                }
            }
            if (gotTarget
                && SpellManager.HasSpell(MultiShot)
                && Me.FocusPercent >= 40
                && !Me.IsChanneling)
            {
                if (SpellManager.CanCast(MultiShot))
                {
                    if (!Me.GroupInfo.IsInRaid
                        && !Me.IsInInstance
                        && !buffExists(Misdirection, Me)
                        && !spellOnCooldown(Misdirection)
                        && lastCast != Misdirection)
                    {
                        Lua.DoString("RunMacroText('/cast [@focus,help][help][@pet,exists] Misdirection');");
                        {
                            LogMsg(">> Misdirection <<", 6);
                        }
                    }
                    SpellManager.Cast(MultiShot);
                    LogMsg("Multi Shot", 6);
                    lastCast = MultiShot;
                    return;
                }
            }
            if (gotTarget
                && SpellManager.HasSpell(ExplosiveTrap)
                && !spellOnCooldown(ExplosiveTrap)
                && Me.HasAura("Trap Launcher")
                && LastSpell != "Explosive Trap"
                && !Me.IsChanneling)
            {
                Lua.DoString("CastSpellByName('Explosive Trap');");
                {
                    SpellManager.ClickRemoteLocation(StyxWoW.Me.CurrentTarget.Location);
                    LogMsg(">> Explosive Trap <<", 6);
                    lastCast = ExplosiveTrap;
                }
            }
            if (gotTarget
                && SpellManager.HasSpell(CobraShot)
                && Me.FocusPercent < 40
                && !Me.IsChanneling)
            {
                if (SpellManager.CanCast(CobraShot))
                {
                    SpellManager.Cast(CobraShot);
                    LogMsg("Cobra Shot", 6);
                    lastCast = CobraShot;
                    return;
                }
            }
            return;
        }
        #region Methods

        #region Buff Checks

        public bool buffExists(int Buff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.GetAuraById(Buff);
                if (Results != null)
                    return true;
            }
            return false;
        }

        public double buffTimeLeft(int Buff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.GetAuraById(Buff);
                if (Results != null)
                {
                    if (Results.TimeLeft.TotalMilliseconds > 0)
                        return Results.TimeLeft.TotalMilliseconds;
                }
            }
            return 0;
        }

        public uint buffStackCount(int Buff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.GetAuraById(Buff);
                if (Results != null)
                    return Results.StackCount;
            }
            return 0;
        }
        #endregion

        #region Cache Checks
        public IEnumerable<WoWAura> cachedAuras = new List<WoWAura>();
        public IEnumerable<WoWAura> cachedTargetAuras = new List<WoWAura>();
        public void getCachedAuras()
        {
            if (Me.CurrentTarget != null)
                cachedTargetAuras = Me.CurrentTarget.GetAllAuras();
            cachedAuras = Me.GetAllAuras();
        }
        #endregion

        #region Cooldown Checks
        private Dictionary<WoWSpell, long> Cooldowns = new Dictionary<WoWSpell, long>();
        public TimeSpan cooldownLeft(int Spell)
        {
            SpellFindResults Results;
            if (SpellManager.FindSpell(Spell, out Results))
            {
                WoWSpell Result = Results.Override ?? Results.Original;
                if (Cooldowns.TryGetValue(Result, out lastUsed))
                {
                    if (DateTime.Now.Ticks < lastUsed)
                        return Result.CooldownTimeLeft;
                    return TimeSpan.MaxValue;
                }
            }
            return TimeSpan.MaxValue;
        }
        long lastUsed;
        public int lastCast;
        public bool onCooldown(int Spell)
        {
            SpellFindResults Results;
            if (SpellManager.FindSpell(Spell, out Results))
            {
                WoWSpell Result = Results.Override ?? Results.Original;
                if (Cooldowns.TryGetValue(Result, out lastUsed))
                {
                    if (DateTime.Now.Ticks < lastUsed)
                        return Result.Cooldown;
                    return false;
                }
            }
            return false;
        }
        public TimeSpan spellCooldownLeft(int Spell, bool useTracker = false)
        {
            if (useTracker)
                return cooldownLeft(Spell);
            SpellFindResults results;
            if (SpellManager.FindSpell(Spell, out results))
            {
                if (results.Override != null)
                    return results.Override.CooldownTimeLeft;
                return results.Override.CooldownTimeLeft;
            }
            return TimeSpan.MaxValue;
        }
        public bool spellOnCooldown(int Spell, bool useTracker = false)
        {
            if (useTracker)
                return !onCooldown(Spell);
            SpellFindResults results;
            if (SpellManager.FindSpell(Spell, out results))
                return results.Override != null ? results.Override.Cooldown : results.Original.Cooldown;
            return false;
        }

        public TimeSpan cooldownLeft(string Spell)
        {
            SpellFindResults Results;
            if (SpellManager.FindSpell(Spell, out Results))
            {
                WoWSpell Result = Results.Override ?? Results.Original;
                if (Cooldowns.TryGetValue(Result, out lastUsed))
                {
                    if (DateTime.Now.Ticks < lastUsed)
                        return Result.CooldownTimeLeft;
                    return TimeSpan.MaxValue;
                }
            }
            return TimeSpan.MaxValue;
        }
        public bool onCooldown(string Spell)
        {
            SpellFindResults Results;
            if (SpellManager.FindSpell(Spell, out Results))
            {
                WoWSpell Result = Results.Override ?? Results.Original;
                if (Cooldowns.TryGetValue(Result, out lastUsed))
                {
                    if (DateTime.Now.Ticks < lastUsed)
                        return Result.Cooldown;
                    return false;
                }
            }
            return false;
        }
        public TimeSpan spellCooldownLeft(string Spell, bool useTracker = false)
        {
            if (useTracker)
                return cooldownLeft(Spell);
            SpellFindResults results;
            if (SpellManager.FindSpell(Spell, out results))
            {
                if (results.Override != null)
                    return results.Override.CooldownTimeLeft;
                return results.Override.CooldownTimeLeft;
            }
            return TimeSpan.MaxValue;
        }
        public bool spellOnCooldown(string Spell, bool useTracker = false)
        {
            if (useTracker)
                return !onCooldown(Spell);
            SpellFindResults results;
            if (SpellManager.FindSpell(Spell, out results))
                return results.Override != null ? results.Override.Cooldown : results.Original.Cooldown;
            return false;
        }



        #endregion

        #region Debuff Checks

        public bool debuffExists(int Debuff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                WoWAura aura = onTarget.GetAllAuras().FirstOrDefault(a => a.SpellId == Debuff && a.CreatorGuid == Me.Guid);
                if (aura != null)
                {
                    return true;
                }
            }
            return false;
        }

        public double debuffTimeLeft(int Debuff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                WoWAura aura = onTarget.GetAllAuras().FirstOrDefault(a =>
                    a.SpellId == Debuff
                    && a.CreatorGuid == Me.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.TimeLeft.TotalMilliseconds;
            }
            return 0;
        }

        public uint debuffStackCount(int Debuff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                WoWAura aura = onTarget.GetAllAuras().FirstOrDefault(a =>
                    a.SpellId == Debuff
                    && a.CreatorGuid == Me.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.StackCount;
            }
            return 0;
        }
        #endregion

        #region Focus checks
        public double Focus
        {
            get
            {
                try
                {
                    using (StyxWoW.Memory.AcquireFrame())
                    {
                        return Styx.WoWInternals.Lua.GetReturnVal<int>("return UnitPower(\"player\");", 0);
                    }
                }
                catch { return 0; }
            }
        }
        #endregion

        #region Macro Checks
        public bool Manual { get { return Convert.ToBoolean(Lua.GetReturnVal<int>("return Manual and 0 or 1", 0)); } }
        public bool useCDs { get { return Convert.ToBoolean(Lua.GetReturnVal<int>("return useCDs and 0 or 1", 0)); } }
        #endregion

        #region Spell Casting
        private Composite autoAttack()
        {
            return
                new PrioritySelector(
                    new Decorator(ret => !StyxWoW.Me.IsAutoAttacking,
                        new Action(ret =>
                        {
                            Lua.DoString("StartAttack()");
                            return RunStatus.Failure;
                        }))
                    );
        }
        private delegate T Selection<out T>(object Context);
        Composite Cast(int Spell, Selection<bool> reqs = null, Selection<WoWUnit> onTarget = null, bool ignoreCanCast = false)
        {
            return
                new Decorator(ret =>
                {
                    if (reqs != null && !reqs(ret))
                        return false;
                    if (!ignoreCanCast && !SpellManager.CanCast(Spell, onTarget != null ? onTarget(ret) : Me.CurrentTarget))
                        return false;
                    return true;
                },
                            new Action(ret =>
                            {
                                WoWSpell castingSpell = Me.CastingSpell;
                                if (castingSpell != null && castingSpell.Id != Spell)
                                    Lua.DoString("SpellStopCasting()");

                                Logging.Write(Colors.Yellow, useSpell(Spell));
                                SpellManager.Cast(Spell, (onTarget != null ? onTarget(ret) : null));
                                lastCast = Spell;
                            })
                    );
        }
        Composite dropCast(int Spell, Selection<bool> reqs = null, Selection<WoWUnit> onTarget = null, bool ignoreCanCast = false)
        {
            return
                new Decorator(ret =>
                {
                    if (reqs != null && !reqs(ret))
                        return false;
                    if (!ignoreCanCast && !SpellManager.CanCast(Spell, onTarget != null ? onTarget(ret) : Me.CurrentTarget))
                        return false;
                    return true;
                },
                            new Action(ret =>
                            {
                                WoWSpell castingSpell = Me.CastingSpell;
                                if (castingSpell != null && castingSpell.Id != Spell)
                                    Lua.DoString("SpellStopCasting()");
                                Logging.Write(Colors.Yellow, useSpell(Spell));
                                SpellManager.Cast(Spell, (onTarget != null ? onTarget(ret) : null));
                                SpellManager.ClickRemoteLocation(Me.CurrentTarget.Location);
                                lastCast = Spell;
                            })
                    );
        }
        #endregion

        #region Target Checks
        internal IEnumerable<WoWUnit> attackableTargets
        {
            get { return ObjectManager.GetObjectsOfType<WoWUnit>(true, false).Where(U => U.Attackable && U.CanSelect && !U.IsFriendly && !U.IsDead && !U.IsNonCombatPet && !U.IsCritter); }
        }
        public bool gotTarget { get { return Me.GotTarget && Me.CurrentTarget != null && Me.CurrentTarget.Attackable && (!Me.CurrentTarget.IsDead && !Me.CurrentTarget.IsFriendly || isTargetDummy); } }
        public bool isTargetDummy { get { return Me.CurrentTarget.Name == "Training Dummy" || Me.CurrentTarget.Name == "Raider's Training Dummy"; } }
        internal IEnumerable<WoWUnit> nearbyTargets(WoWPoint fromLocation, double Radius)
        {
            var Hostile = attackableTargets;
            var maxDistance = Radius * Radius;
            return Hostile.Where(x => x.Location.DistanceSqr(fromLocation) < maxDistance);
        }
        public double targetDistance(WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.DistanceSqr;
                if (Results != null)
                    return onTarget.DistanceSqr;
            }
            return 0;
        }
        public double targetHP(WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.HealthPercent;
                if (Results != null)
                    return onTarget.HealthPercent;
            }
            return 0;
        }
        #endregion

        #region Timer Checks
        private int conv_Date2Timestam(DateTime _time)
        {
            var date1 = new DateTime(1970, 1, 1);
            DateTime date2 = _time;
            var ts = new TimeSpan(date2.Ticks - date1.Ticks);
            return (Convert.ToInt32(ts.TotalSeconds));
        }
        private uint current_life;
        private int current_time;
        private ulong guid;
        private uint first_life;
        private uint first_life_max;
        private int first_time;
        public long targetExistence(WoWUnit onTarget)
        {
            if (onTarget == null) return 0;
            if (isTargetDummy) return 9999;
            if (onTarget.CurrentHealth == 0 || onTarget.IsDead || !onTarget.IsValid || !onTarget.IsAlive)
                return 0;
            if (guid != onTarget.Guid)
            {
                guid = onTarget.Guid;
                first_life = onTarget.CurrentHealth;
                first_life_max = onTarget.MaxHealth;
                first_time = conv_Date2Timestam(DateTime.Now);
            }
            current_life = onTarget.CurrentHealth;
            current_time = conv_Date2Timestam(DateTime.Now);
            var time_diff = current_time - first_time;
            var hp_diff = first_life - current_life;
            if (hp_diff > 0)
            {
                var full_time = time_diff * first_life_max / hp_diff;
                var past_first_time = (first_life_max - first_life) * time_diff / hp_diff;
                var calc_time = first_time - past_first_time + full_time - current_time;
                if (calc_time < 1) calc_time = 99;
                var time_to_die = calc_time;
                var fight_length = full_time;
                return time_to_die;
            }
            if (hp_diff < 0)
            {
                guid = onTarget.Guid;
                first_life = onTarget.CurrentHealth;
                first_life_max = onTarget.MaxHealth;
                first_time = conv_Date2Timestam(DateTime.Now);
                return -1;
            }
            if (current_life == first_life_max)
                return 9999;
            return -1;
        }
        #endregion

        #endregion
    }
}
